#include "OLED_SSD1306.h"
#include "CH341DLL.H"

OLED_SSD1306::OLED_SSD1306(QObject *parent) : QObject(parent){
    /** 配置I2C设备的默认地址、写命令寄存器、写数据寄存器 */
    this->deviceAddress = 0x3C;
    this->commandReg = 0x00;
    this->dataReg = 0x40;
}

void OLED_SSD1306::setDeviceAddress(unsigned char deviceAddress){
    this->deviceAddress = deviceAddress;
}

void OLED_SSD1306::setCommandReg(unsigned char commandReg){
    this->commandReg = commandReg;
}

void OLED_SSD1306::setDataReg(unsigned char dataReg){
    this->dataReg = dataReg;
}

void OLED_SSD1306::OLED_Init(){
    CH341OpenDevice(0);       // 打开设备

    CH341SetStream(0,0x02);   // 设置I2C工作速率

    OLED_WriteCommand(0xAE);  // 关闭显示

    OLED_WriteCommand(0xD5);  // 设置显示时钟分频比/振荡器频率
    OLED_WriteCommand(0x80);

    OLED_WriteCommand(0xA8);  // 设置多路复用率
    OLED_WriteCommand(0x3F);

    OLED_WriteCommand(0xD3);  // 设置显示偏移
    OLED_WriteCommand(0x00);

    OLED_WriteCommand(0x40);  // 设置显示开始行

    OLED_WriteCommand(0xA1);  // 设置左右方向，0xA1正常 0xA0左右反置

    OLED_WriteCommand(0xC8);  // 设置上下方向，0xC8正常 0xC0上下反置

    OLED_WriteCommand(0xDA);  // 设置COM引脚硬件配置
    OLED_WriteCommand(0x12);

    OLED_WriteCommand(0x81);  // 设置对比度控制
    OLED_WriteCommand(0xCF);

    OLED_WriteCommand(0xD9);  // 设置预充电周期
    OLED_WriteCommand(0xF1);

    OLED_WriteCommand(0xDB);  // 设置VCOMH取消选择级别
    OLED_WriteCommand(0x30);

    OLED_WriteCommand(0xA4);  // 设置整个显示打开/关闭

    OLED_WriteCommand(0xA6);  // 设置正常/倒转显示

    OLED_WriteCommand(0x8D);  // 设置充电泵
    OLED_WriteCommand(0x14);

    OLED_WriteCommand(0xAF);  // 开启显示
}

void OLED_SSD1306::OLED_WriteCommand(unsigned char data){
    CH341WriteI2C(0,deviceAddress,0x00,data);
}

void OLED_SSD1306::OLED_WriteData(unsigned char data){
    CH341WriteI2C(0,deviceAddress,0x40,data);
}

void OLED_SSD1306::OLED_Clear(unsigned char color) {
    if(color == 0){
        color = 0x00;
    }else if (color == 1){
        color = 0xFF;
    }
    uint8_t i, j;
    for (j = 0; j < 8; j++) {
        OLED_SetCursor(j, 0);
        for (i = 0; i < 128; i++) {
            OLED_WriteData(color);
        }
    }
}

void OLED_SSD1306::OLED_SetCursor(uint8_t Y, uint8_t X) {
    OLED_WriteCommand(0xB0 | Y);                  // 设置Y位置
    OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4));  // 设置X位置高4位
    OLED_WriteCommand(0x00 | (X & 0x0F));         // 设置X位置低4位
}

void OLED_SSD1306::OLED_SetPixel(uint8_t x, uint8_t y){
    if (x > 127 || y > 63)
        return;
    OLED_Buffer[y / 8][x] = OLED_Buffer[y / 8][x] | (0x01 << (y % 8));
}

void OLED_SSD1306::OLED_NewFrame() {
    memset(OLED_Buffer, 0, sizeof(OLED_Buffer));
}

void OLED_SSD1306::OLED_ShowFrame() {
    for (int i = 0; i < 8; i++) {
        OLED_SetCursor(i, 0);
//        OLED_I2C_Start();
//        OLED_I2C_SendByte(0x78);  // 从机地址
//        OLED_I2C_SendByte(0x40);  // 写数据
//        for (int j = 0; j < 128; j++) {
//            OLED_I2C_SendByte(OLED_Buffer[i][j]);
//            // OLED_WriteData(OLED_Buffer[i][j]);
//        }
//        OLED_I2C_Stop();
    }
}

void OLED_SSD1306::OLED_DrawCircle(uint16_t x0, uint16_t y0, uint8_t r){
    int a, b;
    int di;
    a = 0;
    b = r;              // 初始坐标点
    di = 3 - (r << 1);  // 判断下个点位置的标志
    while (a <= b) {
        OLED_SetPixel(x0 - b, y0 - a);  // 3
        OLED_SetPixel(x0 + b, y0 - a);  // 0
        OLED_SetPixel(x0 - a, y0 + b);  // 1
        OLED_SetPixel(x0 - a, y0 - b);  // 2
        OLED_SetPixel(x0 + b, y0 + a);  // 4
        OLED_SetPixel(x0 + a, y0 - b);  // 5
        OLED_SetPixel(x0 - b, y0 + a);  // 6
        OLED_SetPixel(x0 + a, y0 + b);  // 7
        a++;
        // 使用Bresenham算法画圆
        if (di < 0)
            di += 4 * a + 6;
        else {
            di += 10 + 4 * (a - b);
            b--;
        }
    }
}
